package cate.game.fight.position;

import cate.common.table.d.GDFunc;
import cate.common.table.d.GDPos;
import cate.common.table.d.GDPosition;
import cate.common.table.position.FuncPositionRow;
import cate.common.util.GameResult;
import cate.game.GameBody;
import cate.game.activity.newherotrial.HeroTrialActivity;
import cate.game.event.position.AddPositionRuleEvent;
import cate.game.event.position.UpdatePositionEvent;
import cate.game.fight.msg.FuncPositionUpdateResp;
import cate.game.fight.msg.HeroBatchOffResp;
import cate.game.framework.ModuleMan;
import cate.game.res.holy_pet.HolyPetConstants;
import cate.game.role.Role;
import cate.game.role.bag.hero.Hero;
import cate.game.role.fight.FuncPosition;
import cate.game.role.fight.HeroGrid;
import cate.game.role.fight.Position;
import cate.game.train.hero.msg.HeroLockResp;
import cp.solution.business.game.component.NoticeParam;
import easy.java.dev.note.NoteClass;
import easy.java.practice.errorcode.EcResult;
import org.apache.commons.lang3.StringUtils;

import java.util.HashSet;
import java.util.Set;

@NoteClass("阵法处理")
public class PositionHandler extends ModuleMan {

	@Override
	public void initIndependent(GameBody game) throws Exception {
		super.initIndependent(game);
	}

	@Override
	public void initDependent() throws Exception {

	}

	public void clearPosition(Role role, int funcId){
		FuncPosition funcPosition = role.getFight().clearPosition(funcId);
		if(funcPosition != null){
			role.sendNow(new FuncPositionUpdateResp(funcPosition));
		}
	}

	/**
	 * 更新布阵
	 * @param role
	 * @param funcPosition
	 * @return
	 */
	public EcResult updatePosition(Role role, FuncPosition funcPosition) {
		EcResult r = this.checkFuncPosition(role, funcPosition);
		if(!r.ok()){
			return r;
		}
		handleHeroLock(role, funcPosition);
		role.getFight().addPosition(funcPosition);
		role.sendNow(new FuncPositionUpdateResp(funcPosition));
		publishEvent(game, new UpdatePositionEvent(role, funcPosition));
		return r.success();
	}

	private void handleHeroLock(Role role, FuncPosition funcPosition){
		if (!game.table.position.funcPosition.lockFuncIds.contains(funcPosition.funcId)) {
			return;
		}
		Set<String> oldUids = new HashSet<>();
		FuncPosition oldFuncPosition = role.getFight().funcPositions.get(funcPosition.funcId);
		if(oldFuncPosition != null){
			for(Position position : oldFuncPosition.positions){
				for(HeroGrid grid : position.grids){
					oldUids.add(grid.uid);
				}
			}
		}
		for (Position position : funcPosition.positions) {
			for (HeroGrid grid : position.grids) {
				if (oldUids.contains(grid.uid)) {
					oldUids.remove(grid.uid);
				} else {
					//新上阵的英雄 一定会锁
					Hero hero = role.getBag().hero.getItem(grid.uid);
					if (hero != null && !hero.lock.heroFight) {
						hero.lock.heroFight = true;
						role.sendNow(new HeroLockResp(hero.lock));
					}
				}
			}
		}
		//下阵的英雄 检测一下其他阵型上是否有他
		if(!oldUids.isEmpty()){
			for(String uid : oldUids){
				Hero hero = role.getBag().hero.getItem(uid);
				if(hero != null){
					//此时布阵还没有修改所以要排除掉本布阵
					handleSingleHerolock(role,hero,funcPosition.funcId);
				}
			}
		}
	}

	//单个英雄上阵锁判断
	public void handleSingleHerolock(Role role, Hero hero,int excludeFuncId) {
		boolean change = false;
		if (onLockPosition(role, hero.uid,excludeFuncId)) {
			if (!hero.lock.heroFight) {
				hero.lock.heroFight = true;
				change = true;
			}
		} else {
			if (hero.lock.heroFight) {
				hero.lock.heroFight = false;
				change = true;
			}
		}
		if (change) {
			role.sendNow(new HeroLockResp(hero.lock));
		}
	}
	//英雄是否在锁定的阵容上
	private boolean onLockPosition(Role role, String heroUid,int excludeFuncId) {
		for (Integer lockFuncId : game.table.position.funcPosition.lockFuncIds) {
			if (excludeFuncId > 0 && lockFuncId == excludeFuncId) {
				continue;
			}
			FuncPosition funcPosition = role.getFight().funcPositions.get(lockFuncId);
			if (funcPosition == null) {
				continue;
			}
			if (funcPosition.containHero(heroUid)) {
				return true;
			}
		}
		return false;
	}

	/**
	 * 单英雄一键下阵
	 * @param role
	 * @param heroUid
	 * @return
	 */
	public GameResult<Void> batchOff(Role role, String heroUid) {
		HeroBatchOffResp resp = new HeroBatchOffResp();
		GameResult<Void> r = new GameResult<>();
		resp.heroUid = heroUid;
		for (FuncPosition value : role.getFight().funcPositions.values()) {
			for (Position position : value.positions) {
				FuncPositionRow row = role.getGame().table.position.funcPosition.findRow(value.funcId, position.posNum);
				if (row != null && row.preset && position.containHero(heroUid)) {
					if (position.grids.size() == 1) {
						r.fail(310529, "至少上阵一个英雄", new NoticeParam(NoticeParam.NoticeType.TRANSLATE_STRING, row.nameYID));
						break;
					} else {
						position.grids.removeIf(a -> StringUtils.equals(heroUid, a.uid));
						resp.funcIds.add(value.funcId);
					}
				}
			}
		}
		if (!resp.funcIds.isEmpty()) {
			role.sendNow(resp);
			//更新战力
			if (resp.funcIds.contains(GDFunc.ADVENTURE)) {
				role.getBase().updatePower();
			}
		}
		if (!r.ok()) {
			return r;
		} else {
			//上阵锁通知
			Hero hero = role.getBag().hero.getItem(heroUid);
			if (hero != null) {
				handleSingleHerolock(role, hero, -1);
			}
			return r.success();
		}
	}

	private EcResult checkFuncPosition(Role role,FuncPosition funcPosition){
		EcResult r = new EcResult();
		if (funcPosition == null) {
			return r.fail("阵容不能为空");
		}
		//删除没人的阵容
		if (funcPosition.getPosition(GDPosition.DEFAULT_POS_NUM) == null) {
			return r.fail("队伍1不能为空");
		}
		//添加各个功能的校验规则
		PositionRule customizeRule = new PositionRule(funcPosition.funcId);
		publishEvent(game, new AddPositionRuleEvent(role, customizeRule));

		if (customizeRule.funcPositionRule != null && !customizeRule.funcPositionRule.test(funcPosition)) {
			return r.fail(StringUtils.isBlank(customizeRule.errorMsg) ? "保存阵容失败" : customizeRule.errorMsg);
		}
		//重复性检测
		Set<Integer> heroProtoIds = new HashSet<>();
		Set<Integer> hallowTypes = new HashSet<>();
		for (Position position : funcPosition.positions) {
			if (position.tid > 0 && !role.getRes().formations.isActive(position.tid)) {
				return r.fail("阵型未激活");
			}
			if (game.table.position.funcPosition.findRow(funcPosition.funcId, position.posNum) == null) {
				return r.fail("布阵配置不存在");
			}
			if (customizeRule.positionRule != null && !customizeRule.positionRule.test(position)) {
				return r.fail(StringUtils.isBlank(customizeRule.errorMsg) ? "保存阵容失败" : customizeRule.errorMsg);
			}
			//英雄检测
			Set<Byte> posSet = new HashSet<>();
			if (position.grids.isEmpty()) {
				return r.fail("队伍" + position.posNum + "至少上阵一个英雄");
			}
			for (HeroGrid grid : position.grids) {
				//英雄是否存在检测
				Hero hero = null;
				switch (grid.origin) {
					case GDPosition.Origin.BAG:
						hero = role.getBag().hero.getItem(grid.uid);
						break;
					case GDPosition.Origin.SYSTEM:
						switch (funcPosition.funcId) {
							case GDFunc.ISLAND:
								hero = role.getFarm().island.record.searchAidHero(grid.uid);
								break;
							case GDFunc.NEW_HERO_TRIAL:
								HeroTrialActivity activity = role.getActivity().getEnableActivitySingle(GDFunc.NEW_HERO_TRIAL);
								hero = activity.getAidHero(grid.uid);
								break;
							default:
								break;
						}
						break;
					case GDPosition.Origin.AID:
						hero = role.getFriend().findAidHero(funcPosition.funcId, grid.uid);
						if (hero == null){
							return r.fail("援助英雄不存在");
						}
						break;
					default:
						break;
				}
				if (hero == null) {
					return r.fail("英雄不存在");
				}
				if (hero.lock != null && hero.lock.heroReplace) {
					return r.fail("置换中的英雄无法上阵");
				}
				if (hero.lock != null && hero.lock.heroYoke) {
					return r.fail("羁绊中的英雄无法上阵");
				}
				if (hero.lock != null && hero.lock.heroContract) {
					return r.fail("灵契台中的英雄无法上阵");
				}
				//英雄位置检测
				if (posSet.contains(grid.pos) || !GDPos.valid(grid.pos)) {
					return r.fail("上阵位置有误");
				}
				//重复英雄检测检测
				if (heroProtoIds.contains(hero.getTpl(game.fight.getPlayBuildContext()).protoId)) {
					return r.fail("英雄无法重复上阵");
				}
				if(customizeRule.heroRule != null && !customizeRule.heroRule.test(hero)){
					return r.fail(StringUtils.isBlank(customizeRule.errorMsg) ? "英雄上阵失败":customizeRule.errorMsg);
				}
				//记录位置和英雄id
				posSet.add(grid.pos);
				heroProtoIds.add(hero.getTpl(game.fight.getPlayBuildContext()).protoId);
			}
			//圣器检测
			if (position.hallowType > 0) {
				if (hallowTypes.contains(position.hallowType)) {
					return r.fail("圣器无法重复装备");
				} else {
					if (role.getRes().leader.hallows.getItem(position.hallowType) == null) {
						return r.fail("圣器不存在");
					}
					hallowTypes.add(position.hallowType);
				}
			}
			//灵宠检测
			if (position.holyPetIndex > 0) {
				if (position.holyPetIndex > HolyPetConstants.FIGHT_POS_NUM) {
					return r.fail("灵宠方案不存在");
				}
			}
		}
		return r.success();
	}
}
